package top.hyz.hrm.service.impl;

import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import org.apache.commons.lang.time.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import top.hyz.hrm.StrUtils;
import top.hyz.hrm.ErrorCode;
import top.hyz.hrm.constant.SystemConst;
import top.hyz.hrm.domain.Employee;
import top.hyz.hrm.domain.Tenant;
import top.hyz.hrm.dto.TenantEnteringDto;
import top.hyz.hrm.encrypt.MD5;
import top.hyz.hrm.exception.GlobalException;
import top.hyz.hrm.mapper.EmployeeMapper;
import top.hyz.hrm.mapper.TenantMapper;
import top.hyz.hrm.service.ITenantService;
import top.hyz.hrm.AssertUtils;

import java.util.Date;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author 韩雨泽
 * @since 2021-01-15
 */
@Service
@Transactional(readOnly = true, propagation = Propagation.REQUIRED)
public class TenantServiceImpl extends ServiceImpl<TenantMapper, Tenant> implements ITenantService {
    @Autowired
    private EmployeeMapper employeeMapper;
    /**
     * 盐值长度
     */
    @Value("${hrm.tenant.register.salt-length}")
    private Integer saltLength;
    /**
     * 套餐试用期
     */
    @Value("${hrm.tenant.register.trial-days}")
    private Integer trialDays;
    /**
     * 租户入驻
     * @param tenantEnteringDto 租户入驻Dto对象
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void entering(TenantEnteringDto tenantEnteringDto) {

        //获取租户对象
        Tenant tenant = tenantEnteringDto.getTenant();
        //获取租户管理员对象
        Employee employee = tenantEnteringDto.getEmployee();

        //非空判断
        judgeNotEmpty(tenant, employee, tenantEnteringDto.getMealId());
        //合法性判断
        judgmentLegality(tenant, employee);

        //保存租户信息
        saveTenant(tenant);
        //保存租户管理员信息
        saveEmployee(employee,tenant.getId());
        //保存租户和套餐中间表信息
        saveTenantWithMeal(tenantEnteringDto.getMealId(), tenant.getId(), tenant.getRegisterTime());
    }

    /**
     * 保存租户信息
     * @param tenant 租户对象
     */
    private void saveTenant(Tenant tenant) {

        //设置属性值
        tenant.setRegisterTime(new Date());
        tenant.setState(SystemConst.TENANT_PENDING_STATE);

        //保存租户信息
        baseMapper.insert(tenant);
    }

    /**
     * 保存租户管理员信息
     * @param employee 租户管理员对象
     * @param tenantId 租户id编号
     * @return void
     */
    private void saveEmployee(Employee employee, Long tenantId) {

        //密码加密
        String salt = StrUtils.getRandomString(saltLength);
        String encryptionPassword = MD5.getMD5(employee.getPassword() + salt);

        //设置属性值
        employee.setPassword(encryptionPassword);
        employee.setInputTime(new Date());
        employee.setTenantId(tenantId);
        employee.setSalt(salt);
        employee.setState(SystemConst.EMPLOYEE_NORMAL_STATE);
        employee.setType(5);

        //保存租户管理员信息
        employeeMapper.insert(employee);
    }

    /**
     * 保存租户和套餐中间表信息
     * @param mealId 套餐id编号
     * @param tenantId 租户id编号
     * @param registerTime 租户入驻时间
     */
    private void saveTenantWithMeal(Long mealId, Long tenantId, Date registerTime) {

        //获取套餐过期时间
        Date expireDate = DateUtils.addDays(registerTime, trialDays);

        //保存租户和套餐中间表信息
        baseMapper.insertRelationWithMeal(mealId, tenantId, expireDate);
    }


    /**
     * 非空判断
     * @param tenant 租户对象
     * @param employee 租户管理员对象
     * @param mealId 套餐编号
     */
    private void judgeNotEmpty(Tenant tenant, Employee employee, Long mealId){

        //租户信息校验
        AssertUtils.isNotEmpty(tenant.getCompanyName(),  ErrorCode.COMPANY_NOT_EMPTY_100);
        AssertUtils.isNotEmpty(tenant.getAddress(), ErrorCode.COMPANY_ADDRESS_NOT_EMPTY_101);
        AssertUtils.isNotEmpty(tenant.getCompanyNum(), ErrorCode.COMPANY_UNIFY_THE_SOCIAL_CREDIT_CODE_NOT_EMPTY_102);
        AssertUtils.isNotEmpty(tenant.getLogo(), ErrorCode.COMPANY_LOGO_NOT_EMPTY_103);

        //租户管理员信息校验
        AssertUtils.isNotEmpty(employee.getUsername(), ErrorCode.EMPLOYEE_USERNAME_NOT_EMPTY_104);
        AssertUtils.isNotEmpty(employee.getPassword(), ErrorCode.EMPLOYEE_PASSWORD_NOT_EMPTY_105);
        AssertUtils.isNotEmpty(employee.getTel(), ErrorCode.EMPLOYEE_TEL_NOT_EMPTY_106);
        AssertUtils.isNotEmpty(employee.getEmail(), ErrorCode.EMPLOYEE_EMAIL_NOT_EMPTY_107);

        //套餐和租户类型判断
        AssertUtils.isNotEmpty(mealId, ErrorCode.MEAL_NOT_EMPTY_108);
        AssertUtils.isNotEmpty(tenant.getTenantTypeId(), ErrorCode.TENANT_TYPE_NOT_EMPTY_109);

    }

    /**
     *  合法性判断
     * @param tenant 租户对象
     * @param employee 租户管理员对象
     */
    private void judgmentLegality(Tenant tenant, Employee employee){

        //入驻租户信息合法性判断
        AssertUtils.legalityCheck(tenant.getCompanyNum(), SystemConst.COMPANY_UNIFY_THE_SOCIAL_CREDIT_CODE_REGEX, ErrorCode.ILLEGAL_BUSINESS_201);

        //租户管理员信息合法性判断
        AssertUtils.legalityCheck(employee.getTel(), SystemConst.PHONE_REGEX, ErrorCode.ILLEGAL_TEL_202);
        AssertUtils.legalityCheck(employee.getEmail(), SystemConst.EMAIL_REGEX, ErrorCode.ILLEGAL_EMAIL_203);

    }

    /**
     * 唯一性判断
     * @param tenant 租户对象
     * @param employee 租户管理员对象
     */
    private void judgmentUnique(Tenant tenant, Employee employee ){

        //公司是否已经入驻
        Integer existCountTenant = baseMapper.findCountByCompanyName(tenant.getCompanyName());
        if(existCountTenant > 0) {
            throw  new GlobalException(ErrorCode.REPEATED_TENANT_NAME_302.getMsg());
        }
        //公司管理员是否已经存在
        Integer existCountEmployee = employeeMapper.findCountByUsername(employee.getUsername());
        if(existCountEmployee > 0) {
            throw new GlobalException(ErrorCode.REPEATED_EMPLOYEE_NAME_301.getMsg());
        }

    }
}